#pragma once

/* 
class SubjectManager {
public:
    static SubjectManager * instance(){
        if(SubjectManager::inst == nullptr){
            SubjectManager::inst = new SubjectManager();
        }
        return SubjectManager::inst;
    }

    ~SubjectManager(){
        clear();
    }

    Status insert(const std::string & name, std::shared_ptr<Subject> & sub){
        rocksdb::MutexLock l(&mutex);
        auto it = subjects.find(name);
        if(it == subjects.end()){
            subjects.insert(std::make_pair(name, sub));
            return Status::OK();
        }
        return Status::InvalidArgument(); //subject already exist
    }

    Status get(const std::string & name, std::shared_ptr<Subject> & sub){
        rocksdb::MutexLock l(&mutex);
        auto it = subjects.find(name);
        if(it != subjects.end()){
            sub = it->second;
            return Status::OK();
        }
        return Status::NotFound();//subject not exist
    }
    void clear(){
        rocksdb::MutexLock l(&mutex);
        subjects.clear();
    }
private:
    SubjectManager(){}
    static SubjectManager * inst;

    std::unordered_map<std::string, std::shared_ptr<Subject>> subjects;
    rocksdb::port::Mutex mutex;
};

SubjectManager * SubjectManager::inst = nullptr;

class DB {
public:
    static Status open(std::unique_ptr<DB> & db){
        db = std::unique_ptr<DB>(new DB);
        return Status::OK();
    }
    virtual ~DB(){
        close();
        std::cout << "destructor of DB" << std::endl;
    }
    void close(){
    }

    Status makeSubject(const std::string & name, std::shared_ptr<Subject> & sub){
        assert(!name.empty());
        sub = std::make_shared<Subject>(name);
        return SubjectManager::instance()->insert(name, sub);
    }

    Status getSubject(const std::string & name, std::shared_ptr<Subject> & sub){
        assert(!name.empty());
        return SubjectManager::instance()->get(name, sub);
    }
};



}// namespace streamdb

using namespace streamdb;

void testWrite(){
    std::unique_ptr<streamdb::DB> db;
    auto s = streamdb::DB::open(db);
    if(s.ok()){
        std::shared_ptr<Subject> subject;
        s =  db->makeSubject("subject", subject);
        if(s.ok()){
            subject->append("hello0");
            subject->append("hello1");
            subject->append("hello2");
            subject->append("hello3");
        }
    }
}

void testRead(){
    std::unique_ptr<streamdb::DB> db;
    auto s = streamdb::DB::open(db);
    if(s.ok()){
        std::shared_ptr<Subject> subject;
        s = db->getSubject("subject", subject);
        if(s.ok()){
            std::unique_ptr<Observer> observer(new Observer("client"));
            subject->attch(std::move(observer));

            subject->run(); //wait 

            subject->detach("client");
        }
        else{
            std::cout << "getSubject failed" << std::endl;
        }
    }
}
*/



